package com.chainyoung.component_tmperson.ui.fragment;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.chainyoung.common.appcommon.entity.HdWallet;
import com.chainyoung.common.appcommon.entity.HdWalletCache;
import com.chainyoung.common.appcommon.entity.HdWalletTokenCache;
import com.chainyoung.common.appcommon.entity.HdWalletTokenTransaction;
import com.chainyoung.common.appcommon.entity.HdWalletTransaction;
import com.chainyoung.common.appcommon.hdwallet.CommonTokens;
import com.chainyoung.common.appcommon.hdwallet.TokenBalance;
import com.chainyoung.common.base.BaseFragment;
import com.chainyoung.common.custom_widget.EmptyCallback;
import com.chainyoung.common.di.AppComponent;
import com.chainyoung.component_tmperson.R;
import com.chainyoung.component_tmperson.R2;
import com.chainyoung.component_tmperson.di.component.DaggerPersonFragmentComponent;
import com.chainyoung.component_tmperson.di.module.PersonFragmentModule;
import com.chainyoung.component_tmperson.entity.HdWalletTokenName;
import com.chainyoung.component_tmperson.ui.adapter.HdTransactionListAdapter;
import com.chainyoung.component_tmperson.ui.adapter.HdWalletTokenListAdapter;
import com.chainyoung.component_tmperson.ui.mvp.contract.HdWalletTokenListContract;
import com.chainyoung.component_tmperson.ui.mvp.presenter.HdWalletTokenListPresenter;
import com.google.common.collect.LinkedHashMultiset;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.listener.OnRefreshListener;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;

import static com.chainyoung.common.appcommon.hdwallet.CoinConstant.EMPTY_TOKEN_NAME;
import static com.chainyoung.common.appcommon.hdwallet.CoinConstant.GARBAGE_TOKEN;
import static com.chainyoung.common.appcommon.hdwallet.ExchangeCalculator.ONE_ETHER;


//代币列表
public class HdWalletTokenListFragment extends BaseFragment<HdWalletTokenListPresenter> implements HdWalletTokenListContract.View {


    @BindView(R2.id.rv_list)
    RecyclerView rvList;
    @BindView(R2.id.refresh_layout)
    SmartRefreshLayout refreshLayout;

    private String address;

    private HdWalletTokenListAdapter adapter;

    private List<HdWalletTokenCache> mData = new ArrayList<>();
    private List<String> mContractAddrs = new ArrayList<>();
    private HdWalletCache hdWallet;
    private Map<String, HdWalletTokenName> map = new HashMap<String, HdWalletTokenName>();

    public static HdWalletTokenListFragment newInstance(String address, HdWalletCache hdWallet) {
        HdWalletTokenListFragment fragment = new HdWalletTokenListFragment();
        Bundle args = new Bundle();
        args.putString("address", address);
        args.putSerializable("hdWallet", hdWallet);
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    protected void setupFragmentComponent(AppComponent appComponent) {
        DaggerPersonFragmentComponent.builder()
                .appComponent(appComponent)
                .personFragmentModule(new PersonFragmentModule(this))
                .build()
                .inject(this);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (getArguments() != null) {
            address = getArguments().getString("address");
            hdWallet = (HdWalletCache) getArguments().getSerializable("hdWallet");
        }
    }

    @Override
    protected void initUi() {
        super.initUi();
        initRecylerView();
    }

    @Override
    protected boolean useLoadSir() {
        return true;
    }

    @Override
    protected void onPageRetry(View v) {
        super.onPageRetry(v);
        getAllTokenTransfers();
    }

    private void initRecylerView() {
        adapter = new HdWalletTokenListAdapter(mData, hdWallet);
        DividerItemDecoration itemDecoration = new DividerItemDecoration(mContext, DividerItemDecoration.VERTICAL);
        itemDecoration.setDrawable(ContextCompat.getDrawable(mContext, R.drawable.shape_divider_gray));
        rvList.addItemDecoration(itemDecoration);
        rvList.setLayoutManager(new LinearLayoutManager(mContext));
        rvList.setAdapter(adapter);
        refreshLayout.setEnableLoadMore(false);
        refreshLayout.setOnRefreshListener(new OnRefreshListener() {
            @Override
            public void onRefresh(@NonNull RefreshLayout refreshLayout) {
                getAllTokenTransfers();
            }
        });
    }

    @Override
    protected void initData() {

    }

    @Override
    protected void onFirstUserVisible() {
        getAllTokenCache();
        getAllTokenNames();
    }

    @Override
    public void onUserVisible() {
        super.onUserVisible();
        getAllTokenCache();
        getAllTokenNames();
    }

    @Override
    protected int getLayoutId() {
        return R.layout.tmperson_fragment_hdwallet_token_list;
    }


    //----------------------------------------------------------------------------网络请求-------------------------------------------------------------------------------
    private void getAllTokenTransfers() {
        mPresenter.getAllTokenTransfers(address);
    }

    @Override
    public void onGetAllTokenTransfersSuccessed(String data) {
        List<HdWalletTokenTransaction> datas;
        datas = new Gson().fromJson(data, new TypeToken<List<HdWalletTokenTransaction>>() {
        }.getType());

        /**
         * 处理返回的以太坊代币转账记录，转成本地数据存储
         */
        if (data != null && !datas.isEmpty()) {
            HashMap<String, String[]> map = new HashMap<>();
            for (HdWalletTokenTransaction item : datas) {
                if (!map.containsKey(item.getContractAddress())) {
                    map.put(item.getContractAddress(), new String[]{TextUtils.isEmpty(item.getTokenSymbol()) ? EMPTY_TOKEN_NAME : item.getTokenSymbol(),
                            TextUtils.isEmpty(item.getTokenName()) ? EMPTY_TOKEN_NAME : item.getTokenName()});
                }
            }
            for (Map.Entry<String, String[]> entry : map.entrySet()) {
                if (!entry.getValue()[0].equals(EMPTY_TOKEN_NAME)) {
                    //遍历缓存的contractAddr，如果有新的代币则加入缓存
                    if (!mContractAddrs.contains(entry.getKey())&&!entry.getKey().equals(GARBAGE_TOKEN)) {
                        HdWalletTokenCache tokenCache = new HdWalletTokenCache();
                        tokenCache.setAddress(address);
                        tokenCache.setTokenName(entry.getValue()[1]);
                        tokenCache.setTokenSymbol(entry.getValue()[0]);
                        tokenCache.setContractAddress(entry.getKey());
                        mData.add(tokenCache);
                        mContractAddrs.add(entry.getKey());
                    }
                } else {
                    //匹配没有token name的代币
                    if (!mContractAddrs.contains(entry.getKey())&&!entry.getKey().equals(GARBAGE_TOKEN)) {
                        HdWalletTokenCache tokenCache = new HdWalletTokenCache();
                        tokenCache.setAddress(address);
                        tokenCache.setTokenName(getTokenNameByAddr(entry.getKey()));
                        tokenCache.setTokenSymbol(getTokenSymbolByAddr(entry.getKey()));
                        tokenCache.setContractAddress(entry.getKey());
                        mData.add(tokenCache);
                        mContractAddrs.add(entry.getKey());
                    }
                }
            }
            adapter.notifyDataSetChanged();
            //请求代币余额
            getAllTokenBanlance();
        } else {
            refreshLayout.finishRefresh();
            if (mData.isEmpty()) {
                showPageEmpty();
            } else {
                showPageContent();
            }
        }

    }

    @Override
    public void onGetAllTokenTrasferFailed() {
        refreshLayout.finishRefresh();
    }

    private void getAllTokenBanlance() {
        if (!mData.isEmpty()) {
            for (HdWalletTokenCache item : mData) {
                mPresenter.getTokenBalance(item.getContractAddress(), item.getAddress());
            }
        }
    }

    @Override
    public void onGetTokenBalanceSuccessed(TokenBalance data) {
        refreshLayout.finishRefresh();
        for (HdWalletTokenCache item : mData) {
            if (item.getContractAddress().equals(data.getContractAddress())) {
                item.setBalance(new BigDecimal(data.getBalance()).divide(ONE_ETHER).setScale(4, RoundingMode.DOWN).stripTrailingZeros().toPlainString());
                //更新缓存数据
                updateHdWalletTokenCache(item);
            }
        }
        adapter.notifyDataSetChanged();
        if (mData.isEmpty()) {
            showPageEmpty();
        } else {
            showPageContent();
        }
    }


    @Override
    public void onGetTokenBalanceFailed(String contractAddr) {
        refreshLayout.finishRefresh();
    }


    private void getAllTokenNames() {
        mPresenter.getTokenNames();
    }

    @Override
    public void onGetAllTokenNamesSuccessed(String data) {
        if (TextUtils.isEmpty(data)){return;}
        try {
            Gson gson = new Gson();
            map = gson.fromJson(data, new TypeToken<HashMap<String,HdWalletTokenName>>(){}.getType());
        }catch (Exception e){
            map=new HashMap<String,HdWalletTokenName>();
        }

    }


    //------------------------------------------------------------------------本地数据库缓存----------------------------------------------------------------------------

    private void getAllTokenCache() {
        mPresenter.getAllHdWalletTokenCaches(address);
    }

    @Override
    public void onGetAllHdWalletTokenCaches(List<HdWalletTokenCache> datas) {
        mData.clear();
        if (datas != null) {
            mData.addAll(datas);
        }
        if (!mData.isEmpty()) {
            for (HdWalletTokenCache item : mData) {
                mContractAddrs.add(item.getContractAddress());
            }
        }
        adapter.notifyDataSetChanged();
        getAllTokenTransfers();
    }

    private void updateHdWalletTokenCache(HdWalletTokenCache tokenCache) {
        mPresenter.addHdWalletTokenCache(tokenCache);
    }

    @Override
    public void onAddHdWalletCacheTokenSuccess(HdWalletTokenCache data) {

    }


    private String getTokenNameByAddr(String contractAddr) {
        if (map.containsKey(contractAddr)) {
            return map.get(contractAddr).getSymbol();
        } else {
            return CommonTokens.getTokenNameByAddr(contractAddr);
        }
    }

    private String getTokenSymbolByAddr(String contractAddr) {
        if (map.containsKey(contractAddr)) {
            return map.get(contractAddr).getSymbol();
        } else {
            return CommonTokens.getTokenNameByAddr(contractAddr);
        }
    }
}
